package cn.schoolwow.workflow.module.instance.action.flow.start;

import cn.schoolwow.quickdao.domain.DAO;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import cn.schoolwow.util.domain.check.instance.CheckInstance;
import cn.schoolwow.util.domain.check.instanceList.CheckInstanceList;
import cn.schoolwow.util.domain.query.instanceList.QueryInstanceList;
import cn.schoolwow.workflow.domain.instance.ManualWorkFlowAssigner;
import cn.schoolwow.workflow.domain.instance.StartWorkFlowRequest;
import cn.schoolwow.workflow.entity.WorkFlowDefinition;
import cn.schoolwow.workflow.entity.WorkFlowNode;
import cn.schoolwow.workflow.entity.WorkFlowNodeJump;
import cn.schoolwow.workflow.module.definition.query.service.GetManualWorkFlowAssignerListServiceFlow;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;

import java.util.List;

public class StartWorkFlowQueryFlow implements BusinessFlow {
    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        checkStartWorkFlowRequest(flowContext);
        checkManualWorkFlowAssignerList(flowContext);
        setWorkFlowDefinition(flowContext);
        setStartNode(flowContext);
        setNextNodeList(flowContext);
    }

    @Override
    public String name() {
        return "启动工作流-查询部分";
    }

    private void checkStartWorkFlowRequest(FlowContext flowContext){
        StartWorkFlowRequest startWorkFlowRequest = flowContext.checkInstanceData(StartWorkFlowRequest.class);

        CheckInstance.newCheck()
                .notEmptyCheck(startWorkFlowRequest.definitionName, "流程定义名称");
        if(StringUtils.isBlank(startWorkFlowRequest.instanceName)){
            startWorkFlowRequest.instanceName = startWorkFlowRequest.definitionName;
        }
        CheckInstanceList.newCheck(startWorkFlowRequest.manualWorkFlowAssignerList)
                .notEmptyCheck("nodeName", "发起人自选审批人节点名称")
                .notNullCheck("assignerGroupIndex", "发起人自选审批人序号")
                .notEmptyCheck("nodeName", "发起人自选审批人列表");
    }

    private void checkManualWorkFlowAssignerList(FlowContext flowContext){
        StartWorkFlowRequest startWorkFlowRequest = flowContext.checkInstanceData(StartWorkFlowRequest.class);

        flowContext.startFlow(new GetManualWorkFlowAssignerListServiceFlow())
                .putCurrentCompositeFlowData("definitionName", startWorkFlowRequest.definitionName)
                .execute();
        List<ManualWorkFlowAssigner> manualWorkFlowAssignerList = flowContext.getData("manualWorkFlowAssignerList", List.class);
        if(null==manualWorkFlowAssignerList||manualWorkFlowAssignerList.isEmpty()){
            return;
        }
        if(startWorkFlowRequest.manualWorkFlowAssignerList.isEmpty()){
            throw new IllegalArgumentException("发起流程实例失败!流程存在发起人自选审批人节点!请指定发起人自选审批人列表");
        }
        for(ManualWorkFlowAssigner manualWorkFlowAssigner:manualWorkFlowAssignerList){
            ManualWorkFlowAssigner userManualWorkFlowAssigner = QueryInstanceList.newQuery(startWorkFlowRequest.manualWorkFlowAssignerList)
                    .addQuery("nodeName", manualWorkFlowAssigner.nodeName)
                    .addQuery("assignerGroupIndex", manualWorkFlowAssigner.assignerGroupIndex)
                    .execute()
                    .getOne();
            if(null==userManualWorkFlowAssigner){
                throw new IllegalArgumentException("未指定发起人自选审批人!节点名称:"+manualWorkFlowAssigner.nodeName+",审批人序号:"+manualWorkFlowAssigner.assignerGroupIndex);
            }
            if(null==userManualWorkFlowAssigner.assignerList){
                throw new IllegalArgumentException("发起人自选审批人列表为空!节点名称:"+manualWorkFlowAssigner.nodeName+",审批人序号:"+manualWorkFlowAssigner.assignerGroupIndex);
            }
        }
    }

    private void setWorkFlowDefinition(FlowContext flowContext){
        DAO dao = flowContext.checkInstanceData(DAO.class);
        StartWorkFlowRequest startWorkFlowRequest = flowContext.checkInstanceData(StartWorkFlowRequest.class);

        dao.addRecordString("根据名称查询工作流定义记录");
        WorkFlowDefinition workFlowDefinition = dao.query(WorkFlowDefinition.class)
                .addQuery("name", startWorkFlowRequest.definitionName)
                .execute()
                .getOne();
        Validate.notNull(workFlowDefinition, "工作流定义未部署!工作流定义名称:"+startWorkFlowRequest.definitionName);
        flowContext.putTemporaryInstanceData(workFlowDefinition);
    }

    private void setStartNode(FlowContext flowContext){
        WorkFlowDefinition workFlowDefinition = flowContext.checkInstanceData(WorkFlowDefinition.class);
        DAO dao = flowContext.checkInstanceData(DAO.class);

        dao.addRecordString("查询工作流定义开始节点记录");
        WorkFlowNode startNode = dao.query(WorkFlowNode.class)
                .addQuery("definitionId", workFlowDefinition.getId())
                .addQuery("type", 0)
                .execute()
                .getOne();
        Validate.notNull(workFlowDefinition, "工作流定义不存在开始节点!工作流定义名称:"+workFlowDefinition.getName());
        flowContext.putCurrentFlowData("startNode", startNode);
    }

    private void setNextNodeList(FlowContext flowContext){
        WorkFlowDefinition workFlowDefinition = flowContext.checkInstanceData(WorkFlowDefinition.class);
        WorkFlowNode startNode = flowContext.checkData("startNode", WorkFlowNode.class);
        DAO dao = flowContext.checkInstanceData(DAO.class);

        dao.addRecordString("查询开始节点的后继节点列表");
        List<WorkFlowNode> nextNodeList = dao.query(WorkFlowNode.class)
                .joinTable(WorkFlowNodeJump.class, "id", "nextNodeId")
                .on("definitionId", "definitionId")
                .addQuery("definitionId", workFlowDefinition.getId())
                .addQuery("currentNodeId", startNode.getId())
                .done()
                .execute()
                .getList();
        if(nextNodeList.isEmpty()){
            throw new IllegalArgumentException("开始节点后无后继节点!工作流定义名称:"+workFlowDefinition.getName());
        }
        if(nextNodeList.size()>1){
            throw new IllegalArgumentException("开始节点后存在多个满足条件的后继节点!工作流定义名称:"+workFlowDefinition.getName());
        }
        flowContext.putTemporaryData("nextNode", nextNodeList.get(0));
    }
}
